# waveplugs/infoitem.py
#
#

""" 
    information items .. use !learn <item> is <description> to add an item .. 
    use !? <item> to query the infoitems database.
"""

## gozerlib unports

from gozerlib.tests import tests
from gozerlib.commands import cmnds
from gozerlib.examples import examples
from gozerlib.persist.persist import Persist
from gozerlib.utils.exception import handle_exception
from gozerlib.aliases import getaliases
from gozerlib.aliases import aliasset

## google imports
   
from google.appengine.ext import db

## basic imports

from datetime import datetime
from time import localtime

import thread
import os
import time
import logging

class InfoItem(db.Expando):

    item = db.StringProperty(required=True)
    description = db.StringProperty(required=True)
    creator = db.StringProperty()
    channel = db.StringProperty()
    createtime = db.DateTimeProperty()
    public = db.BooleanProperty(default=True)
   
class InfoItemsDb(object):

    """ information items """

    def add(self, item, description, userhost, ttime, channel="", name=""):
        """ add an item """
        item = item.lower()
        result = 0

        try:
            infoitem = InfoItem(item=item, description=description)
            infoitem.creator = userhost
            infoitem.channel = channel
            infoitem.createtime = datetime.fromtimestamp(ttime)
            infoitem.put()
            result = infoitem.key().id()
        except Exception, ex:
            logging.error("can't add item: %s" % str(ex))
            raise ex

        return result

    def get(self, item):

        """ get infoitems. """

        item = item.lower()
        result = InfoItem.all().filter('item =', item).fetch(1000)
        return result

    def delete(self, indexnr):

        """ delete item with indexnr.  """
        
        item = InfoItem.get(indexnr)

        if item:
            item.delete()
            return True

        return False

    def size(self):

        """ return number of items """

        return InfoItem.all().count()

    def searchitem(self, search):

        """ search items. """

        r = []

        result = InfoItem.all().fetch(1000)

        for res in result:
            if search in res.item:
                r.append(res)

        return r

    def searchdescr(self, search):

        """ search descriptions. """

        r = []
        result = InfoItem.all().fetch(1000)

        for res in result:
            if search in res.description:
                r.append(res)

        return r


info = InfoItemsDb()

assert(info)

def size():

    """ return number of infoitems. """

    return info.size()

def handle_infosize(bot, ievent):

    """ info-size .. show number of information items. """

    ievent.reply("we have %s infoitems" % info.size())

cmnds.add('info-size', handle_infosize, ['USER', 'WEB', 'CLOUD'])
examples.add('info-size', 'show number of infoitems', 'info-size')

def handle_addinfoitem(bot, ievent):

    """ learn <keyword> is <description> .. add information item """

    try:
        (what, description) = ievent.rest.split(' is ', 1)
    except ValueError:
        ievent.reply('<item> is <description>')
        return

    what = what.strip()
    ret = info.add(what, description, ievent.userhost, time.time())

    if ret:
        ievent.reply('item added')
    else:
        ievent.reply('unable to add item')

cmnds.add('info-learn', handle_addinfoitem, ['USER', ], allowqueue=False)
examples.add('learn', 'add description to item', 'learn dunk is top')
aliasset('learn', 'info-learn')

def handle_question(bot, ievent):

    """ ?<keyword> .. ask for information item description. """

    what = ievent.rest

    if not what:
        ievent.reply('i need a argument')
        return

    what = what.strip().lower()
    infoitems = info.get(what)
    result = []

    for item in infoitems:
        result.append(item.description)

    if result:
        ievent.reply("%s is " % what, result)
    else:
        ievent.reply('nothing known about %s' % what)

cmnds.add('info-?', handle_question, ['USER', ], allowqueue=True)
examples.add('info-?', 'show infoitems of <what>', '? test')
aliasset('?', 'info-?')

def handle_showids(bot, ievent):

    """ showid <keyword> .. show ids of item descriptions. """

    what = ievent.rest

    if not what:
        ievent.reply('<item>')
        return

    what = what.strip().lower()
    infoitems = info.get(what)
    result = []

    for item in infoitems:
        result.append("%s (%s)" % (item.description, item.key().id()))

    if result:
        ievent.reply("ids of %s: " % what, result)
    else:
        ievent.reply('nothing known about %s' % what)

cmnds.add('info-showids', handle_showids, ['USER', ], allowqueue=True)
examples.add('info-showids', 'show ids of infoitems descriptions', 'info-showids gozerwave')

def handle_forget(bot, ievent):

    """ 
        forget <keyword> <txttomatch> .. remove information item where \
        description matches txt given.
    """

    try:
        indexnr = int(ievent.args[0])
    except (IndexError, ValueError):
        ievent.reply("<indexnr>")
        return

    nrtimes = info.delete(indexnr)

    if nrtimes:
        ievent.reply('item deleted')
    else:
        ievent.reply('delete %s of %s failed' % (txt, what))

cmnds.add('info-forget', handle_forget, ['FORGET', 'OPER'])
examples.add('info-forget', 'forget <item> containing <txt>', 'info-forget 1001')
aliasset('forget', 'info-forget')

def handle_searchdescr(bot, ievent):

    """ info-sd <txttosearchfor> .. search information items descriptions. """

    if not ievent.rest:
        ievent.missing('<txt>')
        return
    else:
        what = ievent.rest

    what = what.strip().lower()
    result = info.searchdescr(what)

    if result: 
        res = []

        for i in result:
            res.append("[%s] %s" % (i.item, i.description))

        ievent.reply("the following matches %s: " % what, res, dot=True)

    else:
        ievent.reply('none found')

cmnds.add('info-sd', handle_searchdescr, ['USER', 'WEB', 'CLOUD'])
examples.add('info-sd', 'info-sd <txt> ..  search description of infoitems', 'info-sd http')

def handle_searchitem(bot, ievent):

    """ info-si <txt> .. search information keywords """

    if not ievent.rest:
        ievent.missing('<txt>')
        return
    else:
        what = ievent.rest

    what = what.strip().lower()
    result = info.searchitem(what)

    if result:
        res = []

        for i in result:
            res.append("[%s] %s" % (i.item, i.description))

        ievent.reply("the following matches %s: " % what, res, dot=True)

    else:
        ievent.reply('none found')

cmnds.add('info-si', handle_searchitem, ['USER', 'WEB', 'CLOUD'])
examples.add('info-si', 'info-si <txt> ..  search the infoitems keys', 'info-si test')
